芯驰 E3640 启动及刷写分析

#Innolight

当前方案只考虑从 Flash 启动,通过 Boot ROM 将整个程序拷贝到 IRAM 上执行(目前不考虑 Bootloader,升级通过 OTA 进行升级)。本文主要基于 Flash 的启动以及存储结构进行分析。

名词解释

缩写 全称 说明
OTA Over-The-Air 空中下载技术,升级
ROM Read-Only Memory 只读存储器,本文特指存储在片内的 Boot ROM
POR Power-On Reset 上电复位
BPT Boot Package Table Boot Package 头部的信息表
ROT Root of Trust 信任根
SFS Serial Flash Sequence 包含 Flash 的配置信息以及 Boot Package 的存放地址
RFD Region Format Descriptor 描述加密启动时的 Flash Region 的地址范围、密钥等信息
DLP Device Logic Page 设备逻辑页,1 DLP = 512 Bytes
GPT Guid Partition Table 全局唯一标识分区表
SCB System Configuration Block 系统控制块

启动设备

E3 MCU 支持以下启动设备:

芯片通过 Boot Mode Pin(启动模式引脚)的拨码配置来设置相应的启动流程。下表列出 e3_324_dev_kit 参考板使用的启动模式和对应 Boot Mode 拨码位置。

拨码(按照 Boot Pin 3~0 顺序) 启动模式
0000 Nor/Hyper Flash
0010 eMMC
0100 SD Card
1000 USB
1110 Debug

以下为从 Nor/Hyper Flash 模式时拨码开关的位置

Pasted image 20241113144943.png|200
以下为 Debug 模式时拨码开关的位置
Pasted image 20241113145110.png|200

存储器分布

Pasted image 20241021092646.png|550

在如上所示的典型 Flash 存储器分布图中,HyperFlash 的 Sector Size 大小为 256KB(典型值),Nor Flash 的 Sector Size 为 4KB(典型值)。为方便擦写,对 Flash 空间做如下分配:

Warning

GPT 分区表并非必须,如果不使用分区表,该区域可以不预留。

SFS

SFS 包含 Flash 的配置信息以及 Boot Package 的存放地址,存储在 Flash 的起始位置。ROM 程序根据拨码识别到当前启动设备为 Flash 时,首先读取 Flash 中的 SFS 配置信息对 Flash 进行初始化,然后读取 Flash 中的 Boot Package 并完成启动。SFS 的配置详细参数表如下:

偏移(Byte) 大小(Byte) 名称 描述
0x00 4 Tag 0x53465301
0x04 6 INIT_ACT Array 初始化命令组合,最多支持 10 个初始化命令,在 ROM 启动阶段被解析并发送到 Flash。这些命令用于将 Flash 配置到高性能状态。
0x40 16 XFER 读取 XFER 的相关配置
0x50 16 IP Setup XSPI 控制器相关配置
0x60 1 SCLK Freqency 设置 SCLK 时钟频率
0 - Freq0, 25MHZ
1 - Freq1, 50MHZ
2 - Freq2, 66MHZ
3 - Freq3, 100MHZ
4 - Freq4, 125MHZ
0x61 7 Reserved 0
0x67 1 Software Reset Info Boot ROM 会将该值写入 Boot ROM 标志寄存器,并在未熔断(HW Reset)保险丝的情况下向 Nor Flash 发出软件复位(SW Reset)信号
- bit0: ddr or sdr, 1 代表 ddr
- bit1-2: line number, 0, 1, 2, 3 代表 1, 2, 4, 8 线
- bit3-4: 代表使用的 cmd,如下:
cmd = 0x66, 0x99
cmd = 0x9966, 0x6699
cmd = 0xFF, 0xF0
cmd = 0x06, 0xFF
- bit5: invalid or valid, 1 代表 valid 使能
0x68 8 Training Pattern 该数据用于读训练。如果在 IP 特定设置中指定了 PHY 训练,则有效。任何值都可以使用,但推荐使用 0x5AA5F00F_0FF0A55A
0x70 4 Normal Boot Package Normal Boot Package 地址(以 Flash 起始位置为 0 地址),需 4KB 对齐
0x74 4 Backup Boot Package Backup Boot Package 地址(以 Flash 起始地址为 0 地址),需 4KB 对齐
0x78 4 Third Try Boot Package Address Third Try Boot Package 地址(以 Flash 起始地址为 0 地址),需 4KB 对齐
0x7C 4 CRC32 该数据结构的 CRC32 校验和

RFD

RFD 主要是用于加密启动,描述了加密启动的 Flash Region 的地址范围、密钥等信息。E3 的加密启动基于串行 Flash 控制器内嵌的运行时解密模块。加密启动具有如下特点:

E3 系列芯片充分考虑了程序烧写到外部 Flash 的安全性。在自研的串行 Flash 控制 XSPI(支持 1/2/4/8 线,支持 SDR/DDR)中,加入了如下机制保证代码的安全性:

XSPI 控制器支持数据解密功能。加密后的数据烧写 Flash 中(目前仅支持对 NOR Flash 解密),在配置了相应的信息后(RFD),软件可以直接从 XSPI 控制器读出解密后的明文,且这个过程对软件是透明的。E3 最多支持 4 个 RFD,一个 RFD 代表一个加密 Region,每个 RFD 大小是 64 Bytes,其格式如下图:

Pasted image 20241029170459.png|550

从如上框图可知:

Warning

如果 RFD CRC 校验失败,则不会对相应的 Region 做解密操作

Boot Package

Pasted image 20241029170606.png|550

Boot Package 中包含各个核的用户程序,如果 ROM 程序对其校验通过则将其作为下一级启动镜像进行启动。Boot Package 分为三种类型,它们互为冗余:

Boot Package 地址由 SFS 指定,默认按照预留分区表的方式划分,存储地址如下:

Hyper Flash 存储地址 Nor Flash 存储地址
Normal Boot Package 0xC0000 0x7000
Backup Boot Package 0x4C0000 0x407000
Third Try Boot Package 0x8C0000 0x807000

按照 XSPI 控制器在 MCU 中的地址映射,不同类型的 Boot Package 在 MCU 地址空间里的地址为:

Hyper Flash 存储地址 Nor Flash 存储地址
Normal Boot Package 0x100C0000 0x10007000
Backup Boot Package 0x104C0000 0x10407000
Third Try Boot Package 0x108C0000 0x10807000

因为每个 Boot Package 的从起始地址开始的 4096 字节是 BPT,因此镜像组合的起始地址需要在 Boot Package 的地址映射基础上加上 0x1000。

Hyper Flash 存储地址 Nor Flash 存储地址
Normal Boot Package 0x100C1000 0x10008000
Backup Boot Package 0x104C1000 0x10408000
Third Try Boot Package 0x108C1000 0x10808000

BPT

BPT 位于 Boot Package 最前端,共占用 4096(0x1000)个字节,包括以下信息:

Images

Images 是多个核的用户程序镜像组合,包含:

启动流程

Pasted image 20241114100634.png|650

芯片 POR 复位后,当启动核(CPU Cluster0 Core)从复位状态退出时,集成于芯片内部的 ROM 程序在启动核中开始运行,以完成芯片的启动过程。ROM 程序具有以下特点:

  1. ROM 程序根据启动模式引脚,从不同启动设备启动
  2. ROM 程序支持从 Flash 中读取 SFS 配置信息对 Flash 初始化
  3. ROM 程序支持从 Flash 中读取 RFD 配置信息实现加密启动
  4. ROM 程序支持对 Boot Package 验签,以确保各个 Core 依次安全启动
  5. ROM 程序支持从多个 Boot Package 启动

因此在编译完固件之后,需要完成以下步骤来满足 Flash 启动流程:

  1. 将编译得到的各个 Core 的固件合并后签名,得到 Boot Package 文件
  2. 根据 Flash 配置信息生成 SFS 文件
  3. 根据 Flash Region 和密钥等信息生成 RFD 文件(可选)
  4. 将上述三种文件打包在一个 PAC 文件中,使用 SemiDrive 下载工具完成烧写

以下分别介绍两种常见的启动模式:

直接启动

直接启动模式只支持将用户程序程序加载到 IRAM 中运行,不支持从 ROM 直接跳转到 Flash 上 XIP 运行,原因是 XIP 运行前需要对 XSPI 控制器执行 DLL override mode training,training 动作不能在 XIP 运行时执行。

ROM 默认先启动 Image 组合中的 CPU Cluster1/CPU Cluster2,也可以配置为只加载 CPU Cluster1/CPU Cluster2 程序到 IRAM,但不启动 CPU Cluster1/2,最后 ROM 将 CPU Cluster0 启动。

多级启动

多级启动模式下 Boot Package 中只打包一个 image,即 CPU Cluster0 Bootloader(Bootloader 程序由客户自行开发)。多级启动模式支持将用户程序运行在 IRAM 中,或者 XIP 运行,基本流程是:

  1. 上电后 ROM 将 CPU Cluster0 Bootloader 加载到 IRAM,然后跳转过去执行
  2. 如果用户程序以 XIP 模式运行,CPU Cluster0 Bootloader 需要执行 XSPI training
  3. Bootloader 加载 CPU Cluster 0/1/2 的用户程序
  4. Bootloader 启动 CPU Cluster1/2,然后跳转到 Cluster0 用户程序

如果选择 XIP 运行,需要在 Bootloader 中调用驱动完成对 XSPI DLL override mode training 与其他初始化。当 XIP 程序链接地址为 0 时,XIP 程序的大小需要在 4MB 内;当 XIP 程序链接地址与 XIP 程序存储地址一致时,XIP 程序的大小无限制。目前 E3 SSDK 中 XIP demo 全部使用 XIP 程序链接地址与 XIP 程序存储地址一致的方案。

打包流程

Pasted image 20241029171003.png|650

打包的目的是:

  1. 将编译产物 BIN 文件转换为 Boot Package 格式。ROM 启动时需要识别这种格式的文件。
  2. 将 Boot Package 形成 PAC 文件用于下载工具烧录。PAC 文件中包含了 Flashloader 和 SFS 等其他需要烧录或参与烧录过程的文件。

基于 Flash 打包的 PAC 文件包含以下部分:

文件 PAC
Flashloader FDA.img
SFS SFS.img
RFD RFD.img
Normal Boot Package BOOT0.img
Backup Boot Package BOOT1.img(可选)
Third Try Boot Package BOOT2.img(可选)
分区表及分区镜像 可选
用户文件 可指定地址打包

手动打包

  1. 签名形成 Boot Package

编译得到 binary 产物之后,使用 atb_signer 工具可以把编译产物转换为 Boot Package 文件。在该过程中,atb_signer 工具会在 BPT 中生成各个镜像在 Image 组合中的相对位置,镜像 Load 地址,Entry 地址,Hash 校验信息,PSN 信息,以及签名信息,并且把编译产物排列为镜像组合放在 BPT 之后。

sign_tool\windows\atb_signer.exe sign --v 2 --sec_ver 0 --dgst
sha256 --rcp key=sign_tool\keys\TestRSA2048_ossl.pem ^
--iib core=0 type=0x0 image=temp\sf.bin dlp=0x8 to=0x404000
entry=0x404000 ^
--iib core=2 type=0x0 image=temp\sp0.bin dlp=0x100 to=0x600000
entry=0x600000 ^
--iib core=3 type=0x0 image=temp\sp1.bin dlp=0x200 to=0x680000
entry=0x680000 ^
--iib core=4 type=0x0 image=temp\sx0.bin dlp=0x300 to=0x500000
entry=0x500000 ^
--iib core=5 type=0x0 image=temp\sx1.bin dlp=0x400 to=0x580000
entry=0x580000 ^
--psn 0x100 --of temp\ssdk_signed_normal.bin

上述命令的参数解析如下表:

参数 数据
--v 固定写 2,表示当前 atb_signer 的版本
--sec_ver 表示安全启动的版本,ROM 会与 FUSE_PKG_VER [0:127] 中烧写的版本信息进行比较,如果低于 FUSE 中烧写的版本号,则无法用于启动,该功能用于防回滚到
--dgst 指定检验算法的类型(sha256/sha512)
--rcp 表示使用的签名的私钥路径。例如,key=sign_tool\keys\TestRSA204
--iib 每一个 image 都通过一个 --iib 表示,iib 之后的参数为:
- “flag”:值为 0x80 时 ROM 不选择 sp0/sp1/sx0/sx1;值为 0xc0 时 ROM 不加载 sp0/sp1/sx0/sx1;
- “core”:对应镜像属于哪个核,0 表示为 SF Core,2 表示为 SP Core0,3 表示为 SP Core1,4 表示为 SX Core0,5 表示为 SX Core1,6 表示为 SX 为 lockstep 模式,7 表示 SP 为 lockstep 模式;
--psn 指定 PSN 版本号
--of 指定输出文件的路径和格式

上述步骤结束后,最终得到的 Boot Package 文件的路径为:

ssdk\tools\sdtools\temp\ssdk_signed_normal.bin

按照上述命令我们可以依次打包得到 Backup Boot Package 和 Third Try Boot Package。

  1. 打包形成 PAC 文件

该过程会把 Boot Package 文件与 SFS 等文件打包成 PAC 文件,用于 USB 或 JTAG/SWD 下载。

# 进入工具所在路径
cd tools\sdtools\

# 根据 SFS 的配置文件以及分配的 Boot Package 地址形成 SFS 文件,以型号 Cypress 的 Flash 为例生成 SFS 文件
..\..\prebuilts\windows\python-3.7.0\python.exe
pactool\gen_sfs_binary.py
--json sfs\s26h-hyperFlash.json
--out temp\sfs.img
--normal_img_off 0xC0000
--backup_img_off 0x4C0000
--third_img_off 0x8C0000

# 生成 Dloader/Flashloader,工程路径下提供了预编译好的 bianry 文件,拷贝出来直接即可
sign_tool\windows\atb_signer.exe sign --v 2 --sec_ver 0
--dgst sha256 --rcp key=sign_tool\keys\TestRSA2048_ossl.pem
--iib core=0 type=0x0 image=temp\downloader_e3_gateway.bin
to=0x404000 entry=0x404000
--psn 0x01 --of temp\downloader_e3_gateway_signed.bin

# 在 ssdk\tools\sdtools\temp 路径下包含 ssdk_signed_normal.bin ssdk_signed_backup.bin ssdk_signed_thrid.bin sfs.img sf.bin downloader_e3_gateway_signed.bin 文件后执行打包命令就会在 pac\e3_gateway\boot_core\emmc_e3_gateway.pac 路径下生成 pac 文件
pactool\pactool make_pac_image_no_gpt
--output pac\e3_gateway\boot_core\ospi_e3_gateway.pac
--allow_empty_partitions
--da FDA:temp\downloader_e3_gateway_signed.bin
--preload sfs:temp\sfs.img
--preload rfd:rfd\xspi_wrap_rfd_blk_pvk1_ks.rfd
--preload boot0:temp\ssdk_signed_normal.bin
--preload boot1:temp\ssdk_signed_backup.bin
--preload boot2:temp\ssdk_signed_third.bin
参数 数据
make_pac_image_no_gpt 使用无分区表的打包方式
--output 输出的 PAC 包路径
--allow_empty_partitions 运行分区表为空(不使用分区表无效果)
--da downloader(Dloader/Flashloader)所在的路径 Dloader 在 USB 下载过程中被 ROM 下载到 IRAM 中运行,Dloader 完成与 PC 机的通讯,下载 Normal/Backup/Third Try Boot Package 与 SFS 等

Flashloader 在 JTAG/SWD 下载过程中被工具加载到 IRAM 中,工具调用其中的函数下载 Normal/Backup/Third Try Boot Package 与 SFS 等
--preload 所需下载的 Boot Package 以及 SFS、RFD 对应的固件地址。SFS 用于 Flash 启动,RFD 文件用于加密启动

自动打包

利用自动打包脚本 tool/genpac.py 可以完成自动打包流程。genpac.py 可以解析项目的打包配置文件 pac_config.json 进行打包,可以自动完成:

  1. 将编译产物 binary 合成 Boot Package
  2. 选择 SFS 的配置文件,将配置文件转换为 SFS.img 用于打包,同时能够指定 Boot Package 的地址
  3. 选择打包 Dloader 或 Flashloader,对 Dloader 进行签名,Flashloader 不签名
  4. 可以进行加密配置
  5. 形成 SDFactoryTool 软件烧录所需的 PAC 文件
"board": "e3_gateway",
"project": "ref",
"sf_path": "tools\genpac\sf.bin", //示例路径,用户可自行指定绝对路径
"sp0_path": "tools\genpac\sp0.bin", //示例路径,用户可自行指定绝对路径
"sp1_path": "tools\genpac\sp1.bin", //示例路径,用户可自行指定绝对路径
"sx0_path": "tools\genpac\sx0.bin", //示例路径,用户可自行指定绝对路径
"sx1_path": "tools\genpac\sx1.bin", //示例路径,用户可自行指定绝对路径
"downloader_path": "tools\genpac\dloader.bin",
//示例路径,用户可自行指定绝对路径

升级流程

OTA 全称为 Over-The-Air Technology(空中下载技术),是指通过移动通信的接口实现对软件进行远程管理和升级。

OTA 升级过程一般包含四个目标,详见下表说明:

目标 特点 说明
1 静默升级 OTA 不受 MCU 运行状态的影响,即无需 MCU 必须运行在某个状态下才能做升级。例如:要求复位 MCU 进入 Bootloader 程序,然后才能做 OTA。静默升级可以在 APP 内完成,随时接收来自云端升级包,等升级包接收完成后,下次启动时切换。
2 无缝切换 当升级包准备好以后,系统复位时可以选择切换到新系统,这个切换过程无需等待,无需额外的时间成本。
3 支持回滚 升级过程如果被打断,或者升级完成启动新系统出现问题,或者升级完成需要主动回到旧系统,都要能回退到升级前的正常系统。
4 安全启动 在 OTA 之后,系统需要支持安全引导,以确保在启动期间加载正确的升级包。如果没有安全的引导过程,系统可能使用未经授权或损坏的风险代码
基于以上 OTA 升级流程及可实现的目标,OTA 升级可以分为两种类型:

芯驰 E3 MCU OTA 升级方案支持基于 IRAM 和 XIP 完成升级,也称非 XIP 升级方式和 XIP 升级方式。

两种升级方式所支持的功能见下表:

运行方式 静默升级 无缝切换 回滚 安全功能
IRAM 支持 支持 支持 支持
XIP 需要两片 Flash 或双 Die 的 Flash 需两片 Flash 或双 Die 的 Flash 支持 支持
目前的方式考虑基于 IRAM 实现无感升级,可以使用一片式 Flash 实现无感升级:

Pasted image 20241029184935.png|450

ALL-By-ROM 启动

SF-Only 启动

烧录调试

以下基于存储设备是 Flash 的情况,梳理以下烧录和调试的流程:

  1. 如果是调试阶段,程序可以直接烧录到 IRAM 中运行,无需打包成 PAC 格式,重启后 IRAM 中的内容会丢失。
  2. 如果是正式阶段,程序需烧录到 Flash 中,但是执行的模式分为两种,IRAM 和 XIP 运行。XIP 模式下程序被分为 Bootloader 和 App 两部分。Bootloader 运行于 IRAM 上,可以直接擦写 Flash,之后跳转到 App 中 XIP 运行,无法对存储设备(仅 Nor/Hyer Flash 支持 XIP 运行)进行擦写。程序烧录到 Flash 模式下,无论是 IRAM 还是 XIP 运行,都需要烧录 PAC 包,因为 ROM 启动阶段只识别 PAC 格式的包。

XIP 运行前需要对 XSPI 控制器执行 DLL override mode training,training 动作不能在 XIP 运行时执行。所以才需要分为 Bootloader 和 App 两部分。这里可以结合启动流程的直接启动和多级启动的差异部分去理解。